package cn.edu.stu.syllabus.library.star;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;

import cn.edu.stu.syllabus.datas.RequestState;
import cn.edu.stu.syllabus.repository.library.BookStarDataRepository;
import cn.edu.stu.syllabus.repository.library.local.BookEntry;
import cn.edu.stu.syllabus.utils.ExtraNameJoiner;
import cn.edu.stu.syllabus.utils.ListUtils;
import cn.edu.stu.syllabus.utils.RxSchedulerUtils;
import rx.Subscriber;
import rx.Subscription;
import rx.subscriptions.CompositeSubscription;

import static cn.edu.stu.syllabus.utils.NullPointerUtils.checkNotNull;

/**
 * Created by daidaijie on 2017/4/1.
 */

public class BookStarPresenter implements BookStarContract.Presenter {

    private final BookStarContract.View mView;

    private CompositeSubscription mCompositeSubscription;

    private final BookStarDataRepository mBookStarDataRepository;

    private List<BookEntry> mBookEntries;

    private long mLastEndPositionId;

    private int mRequestState;

    private static final int BOOK_PAGE_NUM = 10;

    private static final String EXTRA_BOOK_ENTRY = ExtraNameJoiner.join(
            BookStarPresenter.class, "mBookEntries"
    );

    private static final String EXTRA_LAST_END_POSITION_ID = ExtraNameJoiner.join(
            BookStarPresenter.class, "mLastEndPositionId"
    );

    private static final String EXTRA_REQUEST_STATE = ExtraNameJoiner.join(
            BookStarPresenter.class, "mRequestState"
    );


    @Inject
    public BookStarPresenter(BookStarContract.View view,
                             BookStarDataRepository bookStarDataRepository) {
        mView = checkNotNull(view);
        mBookStarDataRepository = checkNotNull(bookStarDataRepository);
        mCompositeSubscription = new CompositeSubscription();
    }

    @Inject
    public void setupListener() {
        mView.setPresenter(this);
    }

    @Override
    public void subscribe() {
        if (mBookEntries == null) {
            if (RequestState.isEmpty(mRequestState)) {
                mView.showDataEmpty();
            } else if (RequestState.isError(mRequestState)) {
                mView.showDataError();
            } else {
                mRequestState = RequestState.REQUEST_FIRST;
                loadStarBookEntries();
            }
        } else {
            mView.setBookList(mBookEntries);
            if (RequestState.isEmpty(mRequestState)) {
                mView.showLoadingEnd();
            } else if (RequestState.isError(mRequestState)) {
                mView.showLoadingFail();
            }
        }
    }

    @Override
    public void unsubscribe() {
        mCompositeSubscription.unsubscribe();
    }

    @Override
    public void loadStarBookEntries() {
        if (RequestState.isFirst(mRequestState)) {
            mLastEndPositionId = Long.MAX_VALUE;
        }

        Subscription subscription = mBookStarDataRepository
                .getStarBookEntries(mLastEndPositionId, BOOK_PAGE_NUM)
                .compose(RxSchedulerUtils.<List<BookEntry>>io2mainSchedulersTransformer())
                .subscribe(new Subscriber<List<BookEntry>>() {
                    @Override
                    public void onCompleted() {
                    }

                    @Override
                    public void onError(Throwable e) {
                        if (RequestState.isFirst(mRequestState)) {
                            mView.showDataError();
                        } else {
                            mView.showLoadingFail();
                        }
                        mRequestState = RequestState.REQUEST_ERROR;
                    }

                    @Override
                    public void onNext(List<BookEntry> bookEntries) {
                        if (ListUtils.getListSizeSafety(bookEntries) > 0) {
                            if (RequestState.isFirst(mRequestState)) {
                                mBookEntries = bookEntries;
                                mView.setBookList(bookEntries);
                            } else {
                                mView.appendBookList(bookEntries);
                            }
                            mLastEndPositionId = bookEntries.get(bookEntries.size() - 1).getLocalId();
                            mRequestState = RequestState.REQUEST_SUCCESS;
                        } else {
                            if (RequestState.isFirst(mRequestState)) {
                                mView.showDataEmpty();
                            } else {
                                mView.showLoadingEnd();
                            }
                            mRequestState = RequestState.REQUEST_EMPTY;
                        }
                    }
                });

        mCompositeSubscription.add(subscription);
    }

    @Override
    public void unstarBook(BookEntry bookEntry, int position) {
        mBookStarDataRepository.unstarBookEntry(bookEntry);
        mView.removeUnstarBook(position);
    }

    @Override
    public Map<String, Object> getStoreData() {
        Map<String, Object> storeData = new HashMap<>();
        storeData.put(EXTRA_BOOK_ENTRY, mBookEntries);
        storeData.put(EXTRA_LAST_END_POSITION_ID, mLastEndPositionId);
        storeData.put(EXTRA_REQUEST_STATE, mRequestState);
        return storeData;
    }

    @Override
    public void restoreData(Map<String, Object> storeData) {
        mBookEntries = (List<BookEntry>) storeData.get(EXTRA_BOOK_ENTRY);
        mLastEndPositionId = (long) storeData.get(EXTRA_LAST_END_POSITION_ID);
        mRequestState = (int) storeData.get(EXTRA_REQUEST_STATE);
    }
}
